#include "option.h"


option::option()
{
	loadNIDAQConstants();
}
option::option(const option &old)
{
	D=old.D;
	L=old.L;
	S=old.S;
	NIDAQConstants = old.NIDAQConstants;

	map<string,double*>::const_iterator dai;
	for(dai = old.DArray.begin(); dai != old.DArray.end(); ++dai)
	{
		this->DArray[dai->first] = new double[old.getDASize(dai->first)];
		this->DASize[dai->first] = old.getDASize(dai->first);
		for(int i =0; i < DASize[dai->first]; i++)
			*(this->getDArray(dai->first) + i) = *(old.getDArray(dai->first) + i);
	}
}

option::~option(void)
{
	map<string,double*>::const_iterator dai;
	for(dai = this->DArray.begin(); dai != this->DArray.end(); ++dai)
		delete [] dai->second;
}
void option::createarray(string name, long size)
{
	this->DArray[name]= new double[size];
	DASize[name] = size;
}
void option::loadNIDAQConstants(void)
{
	NIDAQConstants["terminalmode"].push_back(DAQmx_Val_Cfg_Default);
	NIDAQConstants["terminalmode"].push_back(DAQmx_Val_RSE);
	NIDAQConstants["terminalmode"].push_back(DAQmx_Val_NRSE);
	NIDAQConstants["terminalmode"].push_back(DAQmx_Val_Diff);

	NIDAQConstants["units"].push_back(DAQmx_Val_Volts);
	NIDAQConstants["units"].push_back(DAQmx_Val_FromCustomScale);

	NIDAQConstants["activeedge"].push_back(DAQmx_Val_Rising);
	NIDAQConstants["activeedge"].push_back(DAQmx_Val_Falling);

	NIDAQConstants["samplemode"].push_back(DAQmx_Val_FiniteSamps);
	NIDAQConstants["samplemode"].push_back(DAQmx_Val_ContSamps);

	NIDAQConstants["transfermech"].push_back(DAQmx_Val_DMA);
	NIDAQConstants["transfermech"].push_back(DAQmx_Val_Interrupts);
	NIDAQConstants["transfermech"].push_back(DAQmx_Val_ProgrammedIO);

	NIDAQConstants["triggerslope"].push_back(DAQmx_Val_RisingSlope);
	NIDAQConstants["triggerslope"].push_back(DAQmx_Val_FallingSlope);
}

std::string option::toString(const char* endline, const char* tab)
{
//ugly use template or fuction call
	stringstream ss;

	map<string,long>::const_iterator li;
	ss << "Long Integer constants are:" << endline;
	for(li=L.begin(); li != L.end(); ++li)
		ss << tab << li->first << tab << li->second << endline;

	map<string,double>::const_iterator di;
	ss << "Double constants are:" << "\n";
	for(di=D.begin(); di != D.end(); ++di)
		ss << tab << di->first << tab << di->second << endline;

	map<string,string>::const_iterator si;
	ss << "String constants are:" << "\n";
	for(si=S.begin(); si != S.end(); ++si)
		ss << tab << si->first << tab << si->second << endline;

	map<string,double*>::const_iterator dai;
	ss << "The double array constants are:" << endline;
	for(dai=DArray.begin(); dai != DArray.end(); ++dai)
		ss << tab  << dai->first << " has a size of " << DASize[dai->first] <<endline;
	return ss.str();
}

void option::fromMathematica(MLINK mlink)
// should return mathlink state and or number of options read in??
{
	string s;
	stringstream ss;
	const char     *ctemp;
	double   d;
	int n1, n2, n3;
	long L;
	string optname;

	MLGetFunction(mlink,&ctemp,&n1);
	ss << ctemp << " has " << n1 << " arguments" << endl;

	string stemp = ctemp;
	MLDisownSymbol(mlink,ctemp);	// direct comparison fails?
	if (stemp != "List")
		bigerror();

	for(long i=0;i<n1; i++)
	{
		MLGetFunction(mlink,&ctemp,&n2);		// should be two item list
		MLGetString(mlink,&ctemp);				// item name
		optname = ctemp;
		ss << "\t variable " << optname << " is an ";
		MLDisownSymbol(mlink,ctemp);

		MLFlush(mlink);
		switch (MLGetNext(mlink))
		{
		case MLTKFUNC:
            MLGetFunction(mlink,&ctemp,&n3);	// for list of reals
			stemp = ctemp;
			MLDisownSymbol(mlink,ctemp);	// direct comparison fails?
			if (stemp != "List")
				bigerror();
			else
			{
				createarray(optname,n3);
				for(int i=0; i < n3; ++i)
				{
					MLGetReal(mlink,&d);
					DArray[optname][i] = d;		// local variable for speed?
				}
			}
			break;
		case MLTKSYM:
	        MLGetSymbol(mlink,&ctemp);
			ss << "Symbol = " << ctemp << "  <== DON'T DO THAT" ;
			break;
		case MLTKINT:
			MLGetLongInteger(mlink,&L);
			this->L[optname] = L;	
			ss << "Integer and = " << L;
			break;
		case MLTKREAL:
			MLGetReal(mlink,&d);
			this->D[optname] = d;
			ss << " Real and = " << d;
			break;
		case MLTKSTR:
			MLGetString(mlink,&ctemp);
			this->S[optname] = 	ctemp;         // is this local need string for map?
			ss << " String and equals \"" << ctemp << "\"";
			break;
		}
		ss << endl;

	}
//	s = ss.str() ;
//	MLPutString(mlink,s.c_str());
	getNIDAQConstants();
	return;	
}
void option::getNIDAQConstants()
{	
	for(map<string,long>::iterator i = L.begin();i!=L.end(); ++i)
	{
		if (NIDAQConstants.find(i->first)!= NIDAQConstants.end())
			i->second = NIDAQConstants[i->first][i->second];
	}	
}


option optionsFromString(std::string s)
{
	option ovt;
	ovt.S[s] = "just a quick test";
	return ovt;
}



void bigerror(void)
{
	MLNewPacket(stdlink);
	MLPutString(stdlink,"BigError");
	return;
}


